#include "compiler.h"

using namespace std;

#define SET_PTR(p, val) if(p) *p = val


/*------------Variant--------------*/
Compiler::Variant::Variant(double value) : type(Type::Value) {
    pData = new double(value);
}
Compiler::Variant::Variant(Oper oper) : type(Type::Oper) {
    pData = new Oper(oper);
}

Compiler::Variant::~Variant() {
    switch(type) {
    case Type::Value:
        delete (const double*)pData;
        break;
    case Type::Oper:
        delete (const Oper*)pData;
        break;
	default:;
    }
}

double Compiler::Variant::toValue() const {
    if(type != Type::Value) throw Error{ "Compiler Error: Variant::toValue()" };
    return *(const double*)pData;
}

Compiler::Variant::Oper Compiler::Variant::toOper() const {
    if(type != Type::Oper) throw Error{ "Compiler Error: Variant::toOper()" };
    return *(const Oper*)pData;
}

void Compiler::Variant::copyFrom(const Variant &other) {
	type = other.type;
    switch(other.type) {
    case Type::Value:
        pData = new double(other.toValue());
        break;
    case Type::Oper:
        pData = new Oper(other.toOper());
        break;
    default:;
    }
}


/*------------Node----------------*/
Compiler::Node::Node(int id, bool isSymbol) : element({id, isSymbol}) {}
Compiler::Node::~Node() {
    if(childs)
        delete[] childs;
}

bool Compiler::Node::analysis(InputList &il, Helper *helper) {
	if(element.isSymbol) {
		if(isNonterminal(element.id)) {
			const map<int, const vector<Element>&> &mapSelect = select[(size_t)element.id];
			auto iter = mapSelect.find(il.current().id);
			if(iter == mapSelect.end())
				return false;
			const vector<Element> elements = (*iter).second;
			childs = new Node[elements.size()];
			childCount = (int)elements.size();
			for(int i = 0; i < (int)elements.size(); i++) {
				const Element &element = elements[(size_t)i];
				Node &child = childs[i];
				child.element = element;
				Helper childHelper(*this, i);
				if(!child.analysis(il, &childHelper))
					return false;
			}
    	} else {
			const Input &input = il.current();
			if(input.id != element.id)
				return false;
			if(input.id == 16) {
				char *endPtr;
				double value = strtod(input.data.c_str(), &endPtr);
				if(endPtr != input.data.c_str() + input.data.length())
					return false;
				data[DataType::Val] = value;
			} else {
				data[DataType::Syn] = (Variant::Oper)input.id;
			}
			il.toNext();
		}
	} else {
		actions[(size_t)element.id](helper);
	}
    return true;
}



/*------------Compiler---------------------*/
double Compiler::parse(const string str, bool *ok) {
	//词法分析
    InputList il;
    smatch match;
    int offset = 0;
    while(regex_search(str.begin() + offset, str.end(), match, regexToken)) {
        if(match.prefix().length() != 0) {
            SET_PTR(ok, false);
            return 0;
        }
        string matchedStr = match.str(1);
        int id = 16;
        if(matchedStr.length() == 1 ) {
            auto iter = mapOper.find(matchedStr[0]);
            if(iter != mapOper.end())
                id = (*iter).second;
        }
        il.vec.push_back(Input{ id, matchedStr });
        offset += match.length();
    }
	il.vec.push_back({9, ""});

    //语法分析
    Node root(0, true);
    try {
        if(!root.analysis(il)) {
            SET_PTR(ok, false);
            return 0;
        }
    } catch(const Error &err) {
        cout << err.what << endl;
        SET_PTR(ok, false);
        return 0;
    }

	Variant var = root.data[Node::DataType::Val];
	if(var.getType() == Variant::Type::Undefined) {
		cout << "Compiler Error: Compiler::Parse()" << endl;
		SET_PTR(ok, false);
		return 0;
	}

    SET_PTR(ok, true);
    return var.toValue();
}

regex Compiler::regexToken(" *(\\+|-|\\*|\\/|\\(|\\)|[\\d.]+)");
map<char, int> Compiler::mapOper = { 
	{'+', 10}, {'-', 11}, {'*', 12}, {'/', 13},
	{'(', 14}, {')', 15}
};

map<int, Compiler::OperFn> Compiler::mapOperFn = {
	{ 10, [](double a, double b){ return a + b; } },
	{ 11, [](double a, double b){ return a - b; } },
	{ 12, [](double a, double b){ return a * b; } },
	{ 13, [](double a, double b){ return a / b; } }
};

vector<vector<Compiler::Element>> Compiler::prods = {
	vector<Element>(),
    { {1, true}, {6, false} },
    { {3, true}, {0, false}, {2, true}, {1, false} },
    { {8, true}, {3, true}, {2, false}, {2, true}, {3, false} },
    { {4, false} },
    { {5, true}, {0, false}, {4, true}, {1, false} },
    { {7, true}, {5, true}, {2, false}, {4, true}, {3, false} },
    { {4, false} },
    { {14, true}, {1, true}, {6, false}, {15, true} },
    { {6, true}, {6, false} },
    { {16, true}, {6, false} },
    { {11, true}, {16, true}, {7, false} },
    { {12, true}, {5, false} },
    { {13, true}, {5, false} },
    { {10, true}, {5, false} },
    { {11, true}, {5, false} }
};
vector<map<int, const vector<Compiler::Element>&>> Compiler::select = {
	{
        { 14, prods[1] }, { 16, prods[1] }, { 11, prods[1] }
    }, {
        { 14, prods[2] }, { 16, prods[2] }, { 11, prods[2] }
    }, {
        { 10, prods[3] }, { 11, prods[3] }, { 15, prods[4] }, { 9, prods[4] }
    }, {
        { 14, prods[5] }, { 16, prods[5] }, { 11, prods[5] }
    }, {
        { 12, prods[6] }, { 13, prods[6] }, { 15, prods[7] }, { 9, prods[7] }, { 10, prods[7] }, { 11, prods[7] }
    }, {
        { 14, prods[8] }, { 16, prods[9] }, { 11, prods[9] }
    }, {
        { 16, prods[10] }, { 11, prods[11] }
    }, {
        { 12, prods[12] }, { 13, prods[13] }
    }, {
        { 10, prods[14] }, { 11, prods[15] }
    }
};

vector<Compiler::ActionFn> Compiler::actions = {
	fnActExpr1, fnActExpr2, fnActExpr3, fnActExpr4, fnActExpr5, fnActSendOper, fnActSendVal, fnActSendNegativeVal
};